﻿using Aliyun.OSS;
using Aliyun.OSS.Common;
using Aliyun.OSS.Util;
using BCService.Common.ExceptionService;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace BCService.Common.OSS
{
    public class OSSObject:IOSSObject
    {
        private readonly ISystemExceptionRecordService systemExceptionRecordService;
        private readonly IOSS oss;
        public OSSObject(IOSS oss,ISystemExceptionRecordService systemExceptionRecordService)
        {
            this.oss = oss;
            this.systemExceptionRecordService = systemExceptionRecordService;
        }

        public ObjectListing ListObjects(string bucketName)
        {
            OssClient client = new OssClient(oss.GetEndpoint(), oss.GetAccessKeyId(), oss.GetAccessKeySecret());
            return client.ListObjects(bucketName);
        }

        public bool DoesObjectExist(string bucketName, string objectName)
        {
            var client = new OssClient(oss.GetEndpoint(), oss.GetAccessKeyId(), oss.GetAccessKeySecret());
            try
            {
                // 判断文件是否存在。
                var exist = client.DoesObjectExist(bucketName, objectName);
                return exist;
            }
            catch (OssException ex)
            {
                Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}",
                    ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
                throw;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed with error info: {0}", ex.Message);
                throw;
            }
        }

        public bool PutObjectCallback(string bucketName, string objectName, string localFileName,string uploadFileRecordNo,out bool fileExists)
        {
            // 创建OssClient实例。
            var client = new OssClient(oss.GetEndpoint(), oss.GetAccessKeyId(), oss.GetAccessKeySecret());
            try
            {
                string responseContent = "";
                //Console.WriteLine("FilePath:" + localFileName);
                var metadata = BuildCallbackMetadata(oss.GetCallbackUrl(), oss.GetCallbackBody(), uploadFileRecordNo);
                using (var fs = File.Open(localFileName, FileMode.Open))
                {
                    var putObjectRequest = new PutObjectRequest(bucketName, objectName, fs, metadata);
                    var result = client.PutObject(putObjectRequest);
                    responseContent = GetCallbackResponse(result);
                }
                //Console.WriteLine("Put object:{0} succeeded, callback response content:{1}", objectName, responseContent);
                fileExists = true;
                return true;
            }
            catch (OssException ex)
            {
                Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID: {2}\tHostID: {3}",
                    ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
                fileExists = true;
                return false;
            }
            //catch (Exception ex)
            //{
            //    Console.WriteLine("Failed with error info: {0}", ex.Message);
            //    fileExists = false;
            //    return false;
            //}
        }
        /// <summary>
        ///  设置上传回调。
        /// </summary>
        /// <param name="callbackUrl">回调地址</param>
        /// <param name="callbackBody">回调内容</param>
        /// <param name="uploadFileRecordNo">上传文件记录编号</param>
        /// <returns></returns>
        private static ObjectMetadata BuildCallbackMetadata(string callbackUrl, string callbackBody,string uploadFileRecordNo)
        {
            string callbackHeaderBuilder = new CallbackHeaderBuilder(callbackUrl, callbackBody).Build();
            string CallbackVariableHeaderBuilder = new CallbackVariableHeaderBuilder().
                AddCallbackVariable("x:upload_file_record_no", "x:"+ uploadFileRecordNo).Build();
            var metadata = new ObjectMetadata();
            metadata.AddHeader(HttpHeaders.Callback, callbackHeaderBuilder);
            metadata.AddHeader(HttpHeaders.CallbackVar, CallbackVariableHeaderBuilder);
            return metadata;
        }
        /// <summary>
        /// 读取上传回调返回的消息内容。
        /// </summary>
        /// <param name="putObjectResult">上传存储对象返回对象</param>
        /// <returns></returns>
        private static string GetCallbackResponse(PutObjectResult putObjectResult)
        {
            string callbackResponse = null;
            using (var stream = putObjectResult.ResponseStream)
            {
                var buffer = new byte[4 * 1024];
                var bytesRead = stream.Read(buffer, 0, buffer.Length);
                callbackResponse = Encoding.Default.GetString(buffer, 0, bytesRead);
            }
            return callbackResponse;
        }
    }
}
